home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Graphics / SPD / Sources / drv_zrtc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-10  |  6.5 KB  |  276 lines  |  [TEXT/R*ch]

  1. /* drvr_zrtc.c - Zortech Flash Graphics specific version of display routines. */
  2.  
  3. /*
  4.  * Modified: 17 Mar 1993
  5.  *           Eduard [esp] Schwan
  6.  *           Passed bg_color to display_init
  7. */
  8.  
  9. #include <dos.h>
  10. #include <io.h>
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <conio.h>
  14. #include <fg.h>
  15. #include "def.h"
  16. #include "drv.h"
  17.  
  18. #define TEST_ABORT if (kbhit() && getch() == 27) { display_close(0); exit(1); }
  19.  
  20. static float X_Display_Scale = 1.0;
  21. static float Y_Display_Scale = 1.0;
  22. int maxx = 320;
  23. int maxy = 200;
  24.  
  25. typedef unsigned char pallette_array[256][3];
  26. pallette_array *pallette = NULL;
  27.  
  28. static fg_box_t clipbox;
  29. static COORD4 bkgnd_color;
  30.  
  31. /* Scale from image size to actual screen pixel size */
  32. static void
  33. rescale_coord(x, y)
  34.     int *x, *y;
  35. {
  36.     float xt, yt;
  37.  
  38.     yt = maxy / 2 + Y_Display_Scale * *y;
  39.     xt = maxx / 2 + X_Display_Scale * *x;
  40.  
  41.     *x = (xt < 0.0 ? 0 : (xt > maxx ? maxx - 1 : (int)xt));
  42.     *y = (yt < 0.0 ? 0 : (yt > maxy ? maxy - 1 : (int)yt));
  43. }
  44.  
  45. /* Set a 256 entry pallette with the values given in "palbuf". */
  46. static void
  47. setmany(unsigned char palbuf[256][3], int start, int count)
  48. {
  49.     unsigned char _far *fp;
  50.     union REGS regs;
  51.     struct SREGS sregs;
  52.     unsigned i;
  53.  
  54. #if defined( __GNUC__ )
  55.     /* This should work for most compilers - only tested with GNU C++, so
  56.        it isn't turned on for anything else */
  57.     for (i=start;i<start+count;i++) {
  58.     regs.x.ax = 0x1010;
  59.     regs.x.bx = i;
  60.     regs.h.ch = palbuf[i][1];
  61.     regs.h.cl = palbuf[i][2];
  62.     regs.h.dh = palbuf[i][0];
  63.     int86x(0x10, ®s, ®s, &sregs);
  64.     return;
  65.     }
  66. #elif defined( DOS386 )
  67.     /* Put the contents of the new palette into real memory, the only
  68.        place I know that won't impact things is the video RAM. */
  69.     fp = MK_FP(_x386_zero_base_selector, 0xA0000);
  70. #elif defined( DOS16RM )
  71.     /* If you aren't using GNU C++ or Zortech C++ for 386 protected mode,
  72.        then you need to be using Zortech C++ for 286 protected mode. */
  73.     fp = MK_FP(0xA000, 0);
  74. #else
  75.     /* This is where you need to add a routine to set the pallette using
  76.        whatever compiler you own. */
  77.     fprintf(stderr, "Unsupported compiler.  Add pallette initialization\n");
  78.     exit(1);
  79. #endif
  80.  
  81.     /* If you got here then you are using Zortech C++ */
  82.     for (i=start;i<start+count;i++) {
  83.     fp[3*(i-start)  ] = palbuf[i][0];
  84.     fp[3*(i-start)+1] = palbuf[i][1];
  85.     fp[3*(i-start)+2] = palbuf[i][2];
  86.     }
  87.  
  88.     regs.x.ax = 0x1012;
  89.     regs.x.bx = start;
  90.     regs.x.cx = count;
  91.     regs.x.dx = 0;
  92.     segread(&sregs);
  93.     sregs.es  = 0xA000;
  94. #if defined( DOS386 )
  95.     int86x_real(0x10, ®s, ®s, &sregs);
  96. #else
  97.     int86x(0x10, ®s, ®s, &sregs);
  98. #endif
  99.     /* Now clear off the values that got dumped into the video RAM */
  100.     for (i=0;i<3*count; i++)
  101.     *fp++ = 0;
  102. }
  103.  
  104. /* Make space for a pallette & make a 332 color map */
  105. static void
  106. pallette_init()
  107. {
  108.     unsigned i, r, g, b;
  109.  
  110.     if (pallette == NULL) {
  111.     pallette = malloc(sizeof(pallette_array));
  112.     if (pallette == NULL) {
  113.         fprintf(stderr, "Failed to allocate pallette array\n");
  114.         exit(1);
  115.     }
  116.     }
  117.  
  118.     i = 0;
  119.     for (r=0;r<8;r++)
  120.     for (g=0;g<8;g++)
  121.         for (b=0;b<4;b++) {
  122.            (*pallette)[i][0] = r << 3;
  123.            (*pallette)[i][1] = g << 3;
  124.            (*pallette)[i][2] = b << 4;
  125.            i++;
  126.         }
  127.     setmany(*pallette, 0, 256);
  128. }
  129.  
  130. /* Turn a RGB color defined as <0, 0, 0> -> <1, 1, 1> into a color that
  131.    is in a 332 pallette. */
  132. static int
  133. determine_color_index(color)
  134.     COORD3 color;
  135. {
  136.     int i;
  137.     unsigned char r, g, b;
  138.  
  139.     i = 255.0 * color[Z];
  140.     if (i<0) i=0;
  141.     else if (i>=256) i = 255;
  142.     b = (unsigned char)i;
  143.  
  144.     i = 255.0 * color[Y];
  145.     if (i<0) i=0;
  146.     else if (i>=256) i = 255;
  147.     g = (unsigned char)i;
  148.  
  149.     i = 255.0 * color[X];
  150.     if (i<0) i=0;
  151.     else if (i>=256) i = 255;
  152.     r = (unsigned char)i;
  153.  
  154.     return (r & 0xE0) | ((g & 0xE0) >> 3) | (b >> 6);
  155. }
  156.  
  157. void
  158. display_clear(void)
  159. {
  160.     /* Proposal: Use "bkgnd_color" to clear screen? [esp] */
  161.  
  162.     /* Clear the screen using a box the size of the screen. */
  163.     fg_fillbox(FG_BLACK, FG_MODE_SET, ~0, fg.displaybox);
  164. }
  165.  
  166. void
  167. display_init(xres, yres, bk_color)
  168.     int xres, yres;
  169.     COORD3 bk_color;
  170. {
  171.     int x, y;
  172.     COORD3 white;
  173.  
  174.     // remember the background color
  175.     COPY_COORD3(bkgnd_color, bk_color);
  176.  
  177.     /* Ignore the resolution and make the display 640x480 in 16 colors. */
  178. #if defined( DOS386 )
  179.     fg_init_vesa1();
  180.     maxx = 640;
  181.     maxy = 480;
  182.     pallette_init();
  183. #else
  184.     fg_init_vga12();
  185.     maxx = 640;
  186.     maxy = 480;
  187. #endif
  188.  
  189.     /* Scale the display to fit onto the screen */
  190.     X_Display_Scale = (xres > maxx ? (float)maxx / (float)xres : 1.0);
  191.     Y_Display_Scale = (yres > maxy ? (float)maxy / (float)yres : 1.0);
  192.     if (X_Display_Scale < Y_Display_Scale)
  193.     Y_Display_Scale = X_Display_Scale;
  194.     else if (Y_Display_Scale < X_Display_Scale)
  195.     X_Display_Scale = Y_Display_Scale;
  196.  
  197.     /* Make the clipping box for the display */
  198.     x = -xres/2; y = -yres/2;
  199.     rescale_coord(&x, &y);
  200.     clipbox[FG_X1] = x;
  201.     clipbox[FG_Y1] = y;
  202.     x = xres/2; y = yres/2-1;
  203.     rescale_coord(&x, &y);
  204.     clipbox[FG_X2] = x;
  205.     clipbox[FG_Y2] = y;
  206.  
  207.     /* Outline the actual "visible" display area in the window */
  208.     SET_COORD3(white, 1.0, 1.0, 1.0);
  209.     display_line(-xres/2, -yres/2, -xres/2, yres/2-1, white);
  210.     display_line( xres/2-1, -yres/2,  xres/2-1, yres/2-1, white);
  211.     display_line(-xres/2,  yres/2-1,  xres/2-1,  yres/2-1, white);
  212.     display_line(-xres/2, -yres/2,  xres/2-1, -yres/2, white);
  213. }
  214.  
  215. void
  216. display_close(int wait_flag)
  217. {
  218.     if (wait_flag) {
  219. #if !defined( _WINDOWS )
  220.     while (!kbhit()) ;
  221. #endif
  222.     if (!getch()) getch();
  223.     }
  224.     if (pallette != NULL)
  225.     free(pallette);
  226.  
  227.     /* Turn off graphics mode */
  228.     fg_term();
  229. }
  230.  
  231. void
  232. display_plot(x, y, color)
  233.     int x, y;
  234.     COORD3 color;
  235. {
  236.     int xp, yp;
  237.  
  238.     xp = x; yp = y;
  239.     rescale_coord(&xp, &yp);
  240.  
  241.     /* Insert code to plot a single pixel here */
  242. #if defined( DOS386 )
  243.     fg_drawdot(determine_color_index(color), FG_MODE_SET, ~0, xp, yp);
  244. #else
  245.     fg_drawdot(FG_WHITE, FG_MODE_SET, ~0, xp, yp);
  246. #endif
  247. }
  248.  
  249. void
  250. display_line(x0, y0, x1, y1, color)
  251.     int x0, y0, x1, y1;
  252.     COORD3 color;
  253. {
  254.     float xt, yt;
  255.     int xs, ys, xe, ye;
  256.     fg_line_t line1;
  257.  
  258.     TEST_ABORT
  259.  
  260.     xs = x0; ys = y0; xe = x1; ye = y1;
  261.     rescale_coord(&xs, &ys);
  262.     rescale_coord(&xe, &ye);
  263.  
  264.     /* Make a line out of the end points */
  265.     fg_make_line(line1, xs, ys, xe, ye);
  266.  
  267.     /* Clip against the view */
  268. #if defined( DOS386 )
  269.     fg_drawlineclip(determine_color_index(color), FG_MODE_SET, ~0,
  270.         FG_LINE_SOLID, line1, clipbox);
  271. #else
  272.     fg_drawlineclip(FG_WHITE, FG_MODE_SET, ~0, FG_LINE_SOLID,
  273.         line1, clipbox);
  274. #endif
  275. }
  276.